package com.xbongbong.parent.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ql.util.express.OperatorOfNumber;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.FilterConditionsPoJo;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.PaasDateUtil;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @version v1.0
 * @date 2020/6/1 10:37
 * @since v1.0
 */
public class ConditionUtil {

    /**
     * 校验是否为同一表单
     * @param targetField
     * @param fieldAttrEntity
     * @param thisFormId
     * @param targetFormId
     * @throws XbbException
     */
    public static void validateTheForm(FieldAttrEntity targetField, FieldAttrEntity fieldAttrEntity, Long thisFormId, Long targetFormId, Integer linkBusinessType, Integer businessType) throws XbbException {
        if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), targetField.getFieldType())) {
            if (Objects.equals(FieldTypeEnum.DATAID.getType(), fieldAttrEntity.getFieldType()) && !Objects.equals(thisFormId, targetField.getLinkInfo().getLinkFormId())) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
            } else if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), fieldAttrEntity.getFieldType())) {
                LinkInfoPojo targetLinkInfoPojo = targetField.getLinkInfo();
                LinkInfoPojo thisLinkInfoPojo = fieldAttrEntity.getLinkInfo();
                if (Objects.equals(SaasMarkEnum.SAAS.getCode(), targetLinkInfoPojo.getLinkSaasMark()) && Objects.equals(targetLinkInfoPojo.getLinkSaasMark(), thisLinkInfoPojo.getLinkSaasMark())
                        && !Objects.equals(targetLinkInfoPojo.getLinkBusinessType(), thisLinkInfoPojo.getLinkBusinessType())) {
                    // 两个都是系统表单，但是表单业务不一样
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
                } else if (Objects.equals(SaasMarkEnum.PAAS.getCode(), targetLinkInfoPojo.getLinkSaasMark()) && Objects.equals(targetLinkInfoPojo.getLinkSaasMark(), thisLinkInfoPojo.getLinkSaasMark())
                        && !Objects.equals(targetLinkInfoPojo.getLinkFormId(), thisLinkInfoPojo.getLinkFormId())) {
                    // 两个都是自定义表单，但是表单id不一样
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
                } else if (!Objects.equals(targetLinkInfoPojo.getLinkSaasMark(), thisLinkInfoPojo.getLinkSaasMark())) {
                    // 一个是saas，一个是paas
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
                }
            } else if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_SINGLE.getType(), fieldAttrEntity.getFieldType()) && !Objects.equals(targetField.getLinkInfo().getLinkBusinessType(), fieldAttrEntity.getLinkedType())) {
                // 当前字段是系统关联字段，需要业务类型一致
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
            }
        } else if (Objects.equals(FieldTypeEnum.DATAID.getType(), targetField.getFieldType())) {
            // 目标表单的字段是数据id
            if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), fieldAttrEntity.getFieldType()) && !Objects.equals(targetFormId, fieldAttrEntity.getLinkInfo().getLinkFormId())) {
                // 当前字段是关联数据，需要表单id一致
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
            } else if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_SINGLE.getType(), fieldAttrEntity.getFieldType()) && !Objects.equals(linkBusinessType, fieldAttrEntity.getLinkedType())) {
                //当前字段是系统关联字段，需要业务类型一致
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
            }
        }else if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_SINGLE.getType(), targetField.getFieldType())) {
            // 目标表单的字段是系统关联字段
            if (Objects.equals(FieldTypeEnum.DATAID.getType(), fieldAttrEntity.getFieldType()) && !Objects.equals(targetField.getLinkedType(), businessType)) {
                // 当前字段是数据id，需要业务类型一致
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
            } else if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), fieldAttrEntity.getFieldType()) && !Objects.equals(targetField.getLinkedType(), fieldAttrEntity.getLinkInfo().getLinkBusinessType())) {
                // 当前字段是关联数据，需要业务类型一致
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
            }else if (Objects.equals(FieldTypeEnum.LINK_BUSINESS_SINGLE.getType(), fieldAttrEntity.getFieldType()) && !Objects.equals(targetField.getLinkedType(), fieldAttrEntity.getLinkedType())) {
                // 当前字段是关联数据，需要业务类型一致
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
            }
        } else if (Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), targetField.getFieldType())) {
            // 目标表单是关联数据多选时，当前表单可以是关联数据和关联数据多选
            if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), fieldAttrEntity.getFieldType()) || Objects.equals(FieldTypeEnum.LINK_DATA_MULTI.getType(), fieldAttrEntity.getFieldType())) {
                LinkInfoPojo targetLinkInfoPojo = targetField.getLinkInfo();
                LinkInfoPojo thisLinkInfoPojo = fieldAttrEntity.getLinkInfo();
                if (Objects.equals(SaasMarkEnum.SAAS.getCode(), targetLinkInfoPojo.getLinkSaasMark()) && Objects.equals(targetLinkInfoPojo.getLinkSaasMark(), thisLinkInfoPojo.getLinkSaasMark())
                        && !Objects.equals(targetLinkInfoPojo.getLinkBusinessType(), thisLinkInfoPojo.getLinkBusinessType())) {
                    // 两个都是系统表单，但是表单业务不一样
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
                } else if (Objects.equals(SaasMarkEnum.PAAS.getCode(), targetLinkInfoPojo.getLinkSaasMark()) && Objects.equals(targetLinkInfoPojo.getLinkSaasMark(), thisLinkInfoPojo.getLinkSaasMark())
                        && !Objects.equals(targetLinkInfoPojo.getLinkFormId(), thisLinkInfoPojo.getLinkFormId())) {
                    // 两个都是自定义表单，但是表单id不一样
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
                } else if (!Objects.equals(targetLinkInfoPojo.getLinkSaasMark(), thisLinkInfoPojo.getLinkSaasMark())) {
                    // 一个是saas，一个是paas
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_SAME);
                }
            }
        }
    }

    /**
     * 判断数据相等以及数字的大于等于等相关判断
     * @param thisValue 本表单字段
     * @param targetValue 目标表单字段
     * @param filterConditionsPoJo 条件实体
     * @return
     */
    public static boolean equals(Object targetValue, Object thisValue, FilterConditionsPoJo filterConditionsPoJo) {
        return equals(targetValue, thisValue, filterConditionsPoJo.getSymbol(), filterConditionsPoJo.getFieldType(), filterConditionsPoJo.getValueFieldType());
    }
    /**
     * @param targetValue
     * @param thisValue
     * @param symbol
     * @param fieldType
     * @param thisFieldType
     * @return boolean
     * @author 吴峰
     * @date 2020/9/29 17:00
     */
    public static boolean equals(Object targetValue, Object thisValue, String symbol, Integer fieldType, Integer thisFieldType) {
        if (Objects.equals(ConditionEnum.EQUAL.getSymbol(), symbol) || Objects.equals(ConditionEnum.INCLUDE.getSymbol(), symbol)) {
            if (thisValue instanceof List) {
                JSONArray conditionValueJson = JSON.parseArray(JSON.toJSONString(thisValue));
                JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(targetValue));
                if (Objects.isNull(jsonArray)) {
                    return false;
                }
                boolean update = conditionValueJson.size() == jsonArray.size();
                if (update) {
                    return Objects.equals(conditionValueJson, jsonArray);
                }
                return false;
            } else {
                if (thisValue instanceof Map && targetValue instanceof Map) {
                    return addressEquals(thisValue, targetValue);
                }
                if (Objects.equals(FieldTypeEnum.LINK_DATA.getType(), fieldType)
                        && Objects.equals(FieldTypeEnum.LINK_DATA.getType(), thisFieldType)) {
                    thisValue = Objects.equals(0, thisValue) ? null : thisValue;
                    targetValue = Objects.equals(0, targetValue) ? null : targetValue;
                }
                if (thisValue instanceof Number && targetValue instanceof Number) {
                    Number a = (Number) targetValue;
                    Number b = (Number) thisValue;
                    int result = OperatorOfNumber.compareNumber(a, b);
                    if (result == 0){
                        return true;
                    }
                    return false;
                }
                return Objects.equals(thisValue, targetValue);
            }
        } else if (Objects.equals(ConditionEnum.NOEQUAL.getSymbol(), symbol)) {
            if (thisValue instanceof List) {
                JSONArray conditionValueJson = JSON.parseArray(JSON.toJSONString(thisValue));
                JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(targetValue));
                if (Objects.isNull(jsonArray)) {
                    return false;
                }
                boolean update = conditionValueJson.size() != jsonArray.size();
                if (update) {
                    return !Objects.equals(conditionValueJson, jsonArray);
                }
                return false;
            } else {
                if (thisValue instanceof  Map && targetValue instanceof Map) {
                    return addressNoEquals(thisValue, targetValue);
                }
                if (thisValue instanceof Number && targetValue instanceof Number) {
                    Number a = (Number) targetValue;
                    Number b = (Number) thisValue;
                    int result = OperatorOfNumber.compareNumber(a, b);
                    if (result != 0){
                        return true;
                    }
                    return false;
                }
                return !Objects.equals(thisValue, targetValue);
            }
        } else if (Objects.equals(ConditionEnum.GREATEREQUAL.getSymbol(), symbol)) {
            if (Objects.isNull(thisValue) || Objects.isNull(targetValue)) {
                return false;
            }
            Number a = (Number) targetValue;
            Number b = (Number) thisValue;
            int result = OperatorOfNumber.compareNumber(a, b);
            if (result >= 0){
                return true;
            }
            return false;
        } else if (Objects.equals(ConditionEnum.GREATERTHAN.getSymbol(), symbol)) {
            if (Objects.isNull(thisValue) || Objects.isNull(targetValue)) {
                return false;
            }
            Number a = (Number) targetValue;
            Number b = (Number) thisValue;
            int result = OperatorOfNumber.compareNumber(a, b);
            if (result > 0){
                return true;
            }
            return false;
        } else if (Objects.equals(ConditionEnum.LESSEQUAL.getSymbol(), symbol)) {

            Number a = (Number) targetValue;
            Number b = (Number) thisValue;
            int result = OperatorOfNumber.compareNumber(a, b);
            if (result <= 0){
                return true;
            }
            return false;
        } else if (Objects.equals(ConditionEnum.RANGE.getSymbol(), symbol))  {
            if (Objects.isNull(thisValue) || Objects.isNull(targetValue)) {
                return false;
            }
            long dateInt = Long.valueOf(String.valueOf(thisValue));
            Long beforeDate = PaasDateUtil.getDateFirstSecond(dateInt);
            Long endDate = PaasDateUtil.getDateLastSecond(dateInt);
            Long targetDate = Long.valueOf(String.valueOf(targetValue));
            // targetDate小于结束日期
            int result = OperatorOfNumber.compareNumber(targetDate, endDate);
            // 起始日期 小于 targetDate
            int result1 = OperatorOfNumber.compareNumber(beforeDate, targetDate);
            if (result<=0 && result1 <=0) {
                return true;
            }
            return false;
        } else if (Objects.equals(ConditionEnum.LESSTHAN.getSymbol(), symbol)) {
            if (Objects.isNull(thisValue) || Objects.isNull(targetValue)) {
                return false;
            }
            Number a = (Number) targetValue;
            Number b = (Number) thisValue;
            int result = OperatorOfNumber.compareNumber(a, b);
            if (result < 0){
                return true;
            }
            return false;
        }

        return false;
    }

    /**
     * 地址之间的判断相等
     * @param thisValue
     * @param targetValue
     * @return
     */
    private static boolean addressEquals(Object thisValue, Object targetValue) {
        JSONObject thisAddress = JSON.parseObject(JSON.toJSONString(thisValue));
        JSONObject targetAddress = JSON.parseObject(JSON.toJSONString(targetValue));
        if (Objects.nonNull(thisAddress) && Objects.nonNull(targetAddress)) {
            boolean provinceSame = Objects.equals(thisAddress.getString(BusinessConstant.PROVINCE), targetAddress.getString(BusinessConstant.PROVINCE));
            boolean citySame = Objects.equals(thisAddress.getString(BusinessConstant.CITY), targetAddress.getString(BusinessConstant.CITY));
            boolean districtSame = Objects.equals(thisAddress.getString(BusinessConstant.DISTRICT), targetAddress.getString(BusinessConstant.DISTRICT));
            boolean addressSame = Objects.equals(thisAddress.getString(BusinessConstant.PROVINCE), targetAddress.getString(BusinessConstant.PROVINCE));
            return provinceSame && citySame && districtSame && addressSame;
        }
        return false;
    }

    private static boolean addressNoEquals(Object thisValue, Object targetValue) {
        JSONObject thisAddress = JSON.parseObject(JSON.toJSONString(thisValue));
        JSONObject targetAddress = JSON.parseObject(JSON.toJSONString(targetValue));
        if (Objects.nonNull(thisAddress) && Objects.nonNull(targetAddress)) {
            boolean provinceSame = !Objects.equals(thisAddress.getString(BusinessConstant.PROVINCE), targetAddress.getString(BusinessConstant.PROVINCE));
            boolean citySame = !Objects.equals(thisAddress.getString(BusinessConstant.CITY), targetAddress.getString(BusinessConstant.CITY));
            boolean districtSame = !Objects.equals(thisAddress.getString(BusinessConstant.DISTRICT), targetAddress.getString(BusinessConstant.DISTRICT));
            boolean addressSame = !Objects.equals(thisAddress.getString(BusinessConstant.PROVINCE), targetAddress.getString(BusinessConstant.PROVINCE));
            return provinceSame && citySame && districtSame && addressSame;
        }
        return false;
    }

    public static Object getRangeTime(String symbol, Object value) {
        if (Objects.equals(ConditionEnum.DYNAMIC.getSymbol(), symbol)) {
            List<Object> dynamicValue = new ArrayList<>();
            if (value instanceof List) {
                dynamicValue = (List<Object>) value;
            } else {
                dynamicValue.add(value);
            }
            try {
                return PaasDateUtil.computeTime(dynamicValue);
            } catch (Exception e) {
                return value;
            }
        }
        if (!Objects.equals(ConditionEnum.RANGE.getSymbol(), symbol) && value instanceof List) {
            List<Object> list = JSON.parseArray(JSON.toJSONString(value));
            if (list.size() == 1) {
                return Long.valueOf(list.get(0).toString());
            }
        }
        return value;
    }

}
